﻿using Qy.Core;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Qy.Scenario;

[AppService]
public class DocPostService : QyRepository<DocPost>
{
    private readonly ApplicationContext _applicationContext;
    private readonly string cacheKey;
    public DocPostService(ApplicationContext applicationContext) : base(applicationContext)
    {
        _applicationContext = applicationContext;
        cacheKey = CacheConst.CACHE_KEY_COUNTARTICLE;
    }

    public async Task<DocPost> GetByUidAsync(int userId, int cid)
    {
        return await Queryable()
            .OrderBy(x => x.Id, OrderByType.Desc)
            .FirstAsync(x => x.Uid == userId && x.Cid == cid);
    }

    /// <summary>
    /// 后台编辑一条信息
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public async Task<EditDocPostAndContent> GetEditAsync(int? id)
    {
        return await Queryable()
               .LeftJoin<DocCat>((data, cat) => data.Cid == cat.Id)
               .LeftJoin<User>((data, cat, user) => data.Uid == user.Id)
               .LeftJoin<UserDept>((data, cat, user, dept) => user.DeptId == dept.Id)
               .LeftJoin<ContentContent>((data, cat, user, dept, contentData) => cat.Id == contentData.Aid)
               .Select((data, cat, user, dept, contentData) => new EditDocPostAndContent()
               {
                   Id = data.Id.SelectAll(),
                   CateName = cat.Name,
                   DeptName = dept.Name
               }, true)
               .FirstAsync(data => data.Id == id);
    }
    /// <summary>
    /// 自动推断新建文号
    /// </summary>
    /// <param name="cid"></param>
    /// <returns></returns>
    public async Task<int> GetByCidAsync(int cid)
    {
        DocPost article = await GetByCid(cid);
        if (article != null && DateTime.Compare(article.Time, new(DateTime.Now.Year, 1, 1)) > 0)
            return article.DocNumber + 1;
        else
            return 1;
    }
    /// <summary>
    /// 列表
    /// </summary>
    /// <param name="articleQuery"></param>
    /// <returns></returns>
    public async Task<PagedInfo<ViewDocPostAndCate>> GetListByCidAdminAsync(QueryDocPost articleQuery)
    {
        articleQuery.Orderby = "Id desc";
        return await GetListAsync(articleQuery);
    }


    /// <summary>
    /// 写入一条新的内容
    /// </summary>
    public virtual async Task<int> InsertAndDataAsync(DocPost docPost, DocPostContent content)
    {
        docPost.DocNumber = await GetByCidAsync(docPost.Cid);
        int pkId = await InsertReturnIdAsync(docPost);
        if (pkId > 0)
        {
            content.Aid = pkId;
            await Context.Insertable(content).IgnoreColumns(true).ExecuteCommandAsync();
            return pkId;
        }
        else return 0;
    }
    /// <summary>
    /// 更新
    /// </summary>
    /// <param name="docPost"></param>
    /// <param name="content"></param>
    /// <returns></returns>
    public virtual async Task<int> UpdateAndContentAsync(DocPost content, DocPostContent contentData)
    {
        if (content != null)
        {
            DocPost getContent = await GetByIdAsync(content.Id);
            contentData.Aid = getContent.Id;

            getContent.Cid = content.Cid;
            getContent.Title = content.Title;
            getContent.Attments = content.Attments;
            getContent.SecretLevel = content.SecretLevel;
            getContent.Department = content.Department;
            getContent.Leader = content.Leader;
            getContent.Examine = content.Examine;
            getContent.Auther = content.Auther;
            getContent.Proofread = content.Proofread;
            getContent.EarlierExa = content.EarlierExa;
            getContent.Remarks = content.Remarks;

            int insertKey = await UpdateAsync(getContent);
            await Context.Storageable(contentData).ExecuteCommandAsync(); //存在更新 不存在插入 (默认是主键)     
            return insertKey;
        }
        else return 0;

    }


    /// <summary>
    /// 删除一条信息
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public virtual async Task<int> DelAndContentAsync(int id)
    {
        if (await DeleteAsync(id) > 0)
        {
            await Context.Deleteable<DocPostContent>(id).ExecuteCommandAsync();
            return 1;
        }
        return 0;
    }

    /// <summary>
    /// 获取列表 
    /// </summary>
    public async Task<PagedInfo<ViewDocPostAndCate>> GetListAsync(QueryDocPost parm)
    {
        DateTime startDate = DateUtility.GetBeginTime(parm.StartDate, -1);
        DateTime endDate = DateUtility.GetBeginTime(parm.EndDate, 1);

        var exp = Expressionable.Create<DocPost>();
        exp = exp.AndIF(parm.Cids != null, docpost => parm.Cids.Contains(docpost.Cid));
        exp = exp.AndIF(parm.StartDate != null && parm.EndDate != null, docpost => docpost.Time >= startDate && docpost.Time <= endDate);
        if (parm.Uids == null)
            exp = exp.And(docpost => docpost.Uid == parm.Uid);
        else
            exp = exp.AndIF(!parm.Uids.Exists(x => x == -1), docpost => parm.Uids.Contains(docpost.Uid));

        return await Queryable()
            .LeftJoin<DocCat>((docpost, cate) => docpost.Cid == cate.Id)
            .LeftJoin<User>((docpost, cate, user) => docpost.Uid == user.Id)
            .LeftJoin<UserDept>((docpost, cate, user, dept) => user.DeptId == dept.Id)
            .LeftJoin<DocPostContent>((docpost, cate, user, dept, contentData) => docpost.Id == contentData.Aid)
            .LeftJoin<DocPostMark>((docpost, cate, user, dept, contentData, mark) => docpost.Id == mark.Aid)
            .Where(exp.ToExpression())
            .WhereIF(parm.NickName != null, (docpost, cate, user) => user.NickName.Contains(parm.NickName))
            .WhereIF(parm.MarkStatus, (docpost, cate, user, dept, contentData, mark) => mark.Status == parm.MarkStatus)
            .WhereIF(parm.FullTextSwitch != 1 && !string.IsNullOrEmpty(parm.Title), (docpost, cate) => docpost.Title.Contains(parm.Title))
            .WhereIF(parm.FullTextSwitch == 1 && !string.IsNullOrEmpty(parm.Title), (docpost, cate, user, dept, contentData) => contentData.Content.Contains(parm.Title))
            .OrderBy((docpost) => docpost.Id, OrderByType.Desc)
            .Select((docpost, cate, user, dept, contentData, mark) => new ViewDocPostAndCate()
            {
                DeptName = dept.Name,
                CateName = cate.Name,
                NickName = user.NickName,
                Uid = user.Id,
                Mark = mark.Mark,
                Id = docpost.Id,
                DocNumber = docpost.DocNumber,
                Time = docpost.Time,
                Title = docpost.Title,
                Cid = docpost.Cid
            })
           .ToPageAsync(parm);
    }


    public async Task<List<CountDocPost>> CountForMonthAsync()
    {
        string cacheName = cacheKey + "ForMonth";
        List<CountDocPost> count = await _applicationContext.ICacheManager.GetAsync<List<CountDocPost>>(cacheName);
        if (count == null)
        {
            count = await CountForMonth();
            await _applicationContext.ICacheManager.SetAsync(cacheName, count, TimeSpan.FromMinutes(11));
        }
        return count;
    }
    public async Task<List<CountDocPost>> CountUserGroupYearAsync()
    {
        string cacheName = cacheKey + "CountUserGroupYearAsync";
        List<CountDocPost> count = await _applicationContext.ICacheManager.GetAsync<List<CountDocPost>>(cacheName);
        if (count == null)
        {
            count = await CountUserGroupYear();
            await _applicationContext.ICacheManager.SetAsync(cacheName, count, TimeSpan.FromMinutes(5));
        }
        return count;
    }



    /// <summary>
    /// 根据CID 查询一条 用于判断当前栏目下有没有数据及查询最新一条信息内容
    /// </summary>
    /// <param name="cid"></param>
    /// <returns></returns>
    public async Task<DocPost> GetByCid(int cid)
    {
        return await Queryable()
            .OrderBy(x => x.Id, OrderByType.Desc)
            .FirstAsync(x => x.Cid == cid);
    }


    /// <summary>
    /// 按栏目统计发布的信息
    /// </summary>
    /// <returns></returns>
    public async Task<List<CountDocPost>> CountForMonth()
    {
        var exp = Expressionable.Create<DocPost>();
        exp = exp.And(data => data.Time.ToString("yyyy-MM") == DateTime.Now.ToString("yyyy-MM"));

        return await Queryable()
            .LeftJoin<DocCat>((data, cat) => data.Cid == cat.Id)
            .Where(exp.ToExpression())
            .GroupBy((data, cat) => new { data.Cid })
            .OrderBy(data=>data.Cid,OrderByType.Desc)
            .Select((data, cat) => new CountDocPost()
            {
                Value = SqlFunc.AggregateCount(data.Id),
                Cids = data.Cid,
                Name = cat.Name,
            })
            .ToListAsync();
    }

    /// <summary>
    /// 按用户统计发布的信息量 排名
    /// </summary>
    /// <returns></returns>
    public async Task<List<CountDocPost>> CountForUser()
    {
        var exp = Expressionable.Create<DocPost>();
        exp = exp.And(data => data.Time.ToString("yyyy-MM") == DateTime.Now.ToString("yyyy-MM"));

        return await Queryable()
            .LeftJoin<DocPostMark>((data, mark) => data.Cid == mark.Id)
            .LeftJoin<User>((data, mark,user) => data.Uid == user.Id)
            .Where(exp.ToExpression())
            .GroupBy((data) => new { data.Cid })
            .OrderBy(data => data.Cid)
            .Select((data, mark,user) => new CountDocPost()
            {
                Value = SqlFunc.AggregateCount(data.Id),
                Cids = data.Cid,
                Name = user.NickName,
                Uids=data.Uid,
                MarkNum= SqlFunc.AggregateSum(SqlFunc.IF(mark.Aid == data.Id).Return(1).End(0))
            })
            .ToListAsync();
    }

    /// <summary>
    /// 按角色统计本月发布的信息量
    /// </summary>
    /// <returns></returns>
    public async Task<List<CountDocPost>> CountUserGroupYear()
    {
        var exp = Expressionable.Create<DocPost>();
        exp = exp.And(data => data.Time.ToString("yyyy-MM") == DateTime.Now.ToString("yyyy-MM"));

        return await Queryable()
            .LeftJoin<UserDept>((data, dept) => data.Uid == dept.Id)
            .LeftJoin<User>((data, mark, user) => data.Uid == user.Id)
            .Where(exp.ToExpression())
            .GroupBy((data) => new { data.Uid })
            .OrderBy(data => data.Uid)
            .Select((data, dept, user) => new CountDocPost()
            {
                Value = SqlFunc.AggregateCount(data.Id),
                Cids = data.Cid,
                Name = dept.Name,
                Uids = data.Uid,
            })
            .ToListAsync();
    }

   
}
